package org.pwwong.fxscalautils.components.controls

import com.sun.scenario.scenegraph.fx.FXShape
import com.sun.scenario.scenegraph.SGAbstractShape

import java.awt

import org.pwwong.fxscalautils.components.layouthints._
import org.pwwong.fxscalautils.graphics._
import org.pwwong.fxscalautils.Predef._

import org.pwwong.scalautils.property._
import org.pwwong.scalautils.event._
import org.pwwong.scalautils.signals._
import org.pwwong.scalautils.signals.Predef._

object Rectangle { def apply() = new Rectangle }
class Rectangle extends RectangularShape[awt.Rectangle](new awt.Rectangle){
  onAnyChanges(curWidth,curHeight)(this){ 
    compNodeImpl.setShape({shape().width=curWidth().toInt; shape().height=curHeight().toInt; shape()})
  }
}

object RoundRectangle { def apply() = new RoundRectangle }
class RoundRectangle extends RectangularShape[awt.geom.RoundRectangle2D.Double](new awt.geom.RoundRectangle2D.Double){
  val cornerRadius = Property[Double](0.0)  
  cornerRadius.onChangeAndOnce(this){ 
    newCornerRadius => 
    compNodeImpl.setShape{
      shape().arcwidth = newCornerRadius
      shape().archeight = newCornerRadius 
      shape()
    } 
  }
  onAnyChanges(curWidth,curHeight)(this){ 
    compNodeImpl.setShape{ 
      shape().width=curWidth().toInt
      shape().height=curHeight().toInt
      shape()
    }
  }
}

abstract class RectangularShape[RectangularShapeType<:awt.geom.RectangularShape](_initShape:RectangularShapeType) 
               extends Shape[RectangularShapeType](_initShape) {}

abstract class Shape[ShapeType<:awt.Shape](initShape:ShapeType) extends Component {
  type FXImpl = FXShape
  compNodeImpl = new FXShape
  
  w(*) h(*)
  
  val shape = Property[ShapeType](initShape)
  val fillPaint = Property[awt.Paint](ClearColor())
  val border = Property[awt.Stroke](EmptyStroke())
  val borderPaint = Property[awt.Paint](ClearColor())
  
  onAnyChanges(fillPaint,border,borderPaint)(this){ 
    compNodeImpl.setMode{
      if(fillPaint().getTransparency != 0)
        if(borderPaint().getTransparency != 0) SGAbstractShape.Mode.STROKE_FILL
        else SGAbstractShape.Mode.FILL
      else
        SGAbstractShape.Mode.STROKE
    }
  }
  
  // Size
  override val preferredWidth = curWidth
  override val preferredHeight = curHeight
  
  // Reactions
  shape.onChangeAndOnce(this){ compNodeImpl.setShape(_) }
  fillPaint.onChangeAndOnce(this){ compNodeImpl.setFillPaint(_)  }
  borderPaint.onChangeAndOnce(this){ compNodeImpl.setDrawPaint(_)  }
  border.onChangeAndOnce(this){ compNodeImpl.setDrawStroke(_) }
}
